﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web.Http;
using Sustainalytics.Claims;
using Sustainalytics.DataLayer;
using Sustainalytics.Entities;
using Sustainalytics.OAuth.Services.Common;
using Sustainalytics.Portfolios.BL;
using Sustainalytics.Portfolios.BL.Exceptions;
using Sustainalytics.Portfolios.Service.ErrorCodes;
using Sustainalytics.Portfolios.Service.Models;
using Sustainalytics.Portfolios.Service.Utility;
using Sustainalytics.Utils;
using WebApi.OutputCache.V2;

namespace Sustainalytics.Portfolios.Service.Controllers
{
    //[AutoInvalidateCacheOutput]
    [RoutePrefix("api/v1/portfolios/{portfolioId}/portfolioCompanies")]
    public class PortfoliosDetailsController : ApiController, IPortfolioDetailsController
    public class PortfoliosCompanyController : ApiController
    {
        static IPortfolioCompanyManagement _portfolio;
        static IPortfolioCompanyRepository _portfolioCompanyRepo = null;
        static IClaimsChecker claimsChecker;

        public PortfoliosDetailsController()
        {
            
        }

        static PortfoliosDetailsController()
        {
            if (!UnitTestDetector.IsInUnitTest)
            {
                claimsChecker = new ClaimsChecker();
            }
            //_portfolioCompanyRepo = PortfolioCompanyRepository.GetPortfolioCompanyRepository(ConfigurationManager.ConnectionStrings["ClientPlatform"].ConnectionString);
            //_portfolio = new PortfolioCompanyManagement(_portfolioCompanyRepo);
            //claimsChecker = new ClaimsChecker();
        }

        public PortfoliosDetailsController(IClaimsChecker claimC)
        {
              _portfolioDetailsRepo = PortfolioDetailsRepository.GetPortfolioDetailsRepository("mongodb://localhost/ClientPlatform_Test");
              _portfolioDetails = new PortfolioDetailsManagement(_portfolioDetailsRepo);
              claimsChecker = claimC;
        }

        public PortfoliosDetailsController(PortfolioDetailsManagement portfolioDetailsManagement, IClaimsChecker claimC)
        {
            _portfolioDetails = portfolioDetailsManagement;
            claimsChecker = claimC;
        }

       // [CacheOutput(ServerTimeSpan = 100, ClientTimeSpan = 0, NoCache = true, MustRevalidate = true, Private = true)]
        [Route("")]
        public HttpResponseMessage Get(Guid portfolioId, [FromUri] ListOptions listOptions, string UserId
// todo ileana: at the first view, accountid may be removed from this list - review moving user from account to account 
            // kept here just for caching 
            )
        {
            try
            {
                if (!claimsChecker.ValidatePortfolioManagementClaim(this))
                    throw new PortfolioManagementClaimNull();

                PortfolioUserClaims userClaims = new PortfolioUserClaims();

                //if (Utils.UnitTestDetector.IsInUnitTest)
                //{
                //    userClaims.AddedByUserId = new Guid("4387c2a7-1eda-11e4-92ce-6c3be5be9f98");
                //    userClaims.AddedByUserName = "ileana.popescu@sustainalytics.com";
                //    userClaims.AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98");
                //}
                //else
                //{
                    if (ClaimsPrincipal.Current != null && ClaimsPrincipal.Current.Claims != null)
                    {
                        userClaims.AddedByUserId = new Guid(ClaimsPrincipal.Current.Claims.Where(c => c.Type == ClaimTypes.NameIdentifier).SingleOrDefault().Value);
                        userClaims.AddedByUserName = ClaimsPrincipal.Current.Identity.Name.ToLowerInvariant();
                        userClaims.AccountId = new Guid(ClaimsPrincipal.Current.Claims.Where(c => c.Type == CustomClaimTypes.AccountId).SingleOrDefault().Value);
                    }
                //}

                PortfolioDetailsFilter filter = new PortfolioDetailsFilter
                {
                    PortfolioId = portfolioId
                };

                if (listOptions.GetCount)
                {
                    int count = _portfolioDetails.GetPortfolioDetailsCount(filter, userClaims);
                    return Request.CreateResponse(HttpStatusCode.OK, new { PortfolioDetailsCount = count });
                }
                else
                {
                    var porfolioDetails = _portfolioDetails.GetPortfolioDetails(filter, userClaims, listOptions.Skip, listOptions.Take, listOptions.OrderBy, listOptions.OrderAscending);

                    if (porfolioDetails != null)
                    {
                        //TODO:Ileana - send PortfolioDetailsDto to UI (create PortfolioDetailsDto)
                        //if (listOptions.IncludeAllFields)
                        //{
                        //    List<PortfolioDetailsDto> portfolioDetailsList = porfolioDetails.Select(p => PortfolioCompanyDto.CreateFull(p)).ToList();
                        //    return Request.CreateResponse(HttpStatusCode.OK, portfolioDetailsList);
                        //}
                        //else
                        //{
                        //    List<PortfolioCompanyBaseDto> portfolioDetailsList = porfolioDetails.Select(p => PortfolioCompanyDto.CreateLess(p)).ToList();
                        //    return Request.CreateResponse(HttpStatusCode.OK, portfolioDetailsList);
                        //}
                    }
                    return Request.CreateResponse(HttpStatusCode.OK);
                }
            }
            catch (PortfolioManagementClaimNull)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden, new { ErrorCode = PortfoliosErrorCodes.PortfolioManagementClaimNull });
            }
            catch (Exception)
            {
                //PortfolioManagementEventSource.Log.GetPortfoliosError(ex);
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorCode = 1010 });
            }
        }

        [Route("{id}")]
        public HttpResponseMessage Post(Guid portfolioId, Guid id)
        {
            try
            {
                if (!claimsChecker.ValidatePortfolioManagementClaim(this))
                    throw new PortfolioManagementClaimNull();

                PortfolioUserClaims userClaims = new PortfolioUserClaims();

                //if (Utils.UnitTestDetector.IsInUnitTest)
                //{
                //    userClaims.AddedByUserName = "ileana.popescu@sustainalytics.com";
                //    userClaims.AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98");
                //}
                //else
                //{
                    if (ClaimsPrincipal.Current != null && ClaimsPrincipal.Current.Claims != null)
                    {
                        userClaims.AddedByUserName = ClaimsPrincipal.Current.Identity.Name.ToLowerInvariant();
                        userClaims.AccountId = new Guid(ClaimsPrincipal.Current.Claims.Where(c => c.Type == CustomClaimTypes.AccountId).SingleOrDefault().Value);
                    }
                //}
                //TODO: Guid id => companyId - search for SecurityId
                //_portfolioDetails.InsertPortfolioDetails(portfolioId, id, userClaims);
                
                //invalidate cache for parent resource 
                var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request);
                cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey("Portfolios", "Get"));

                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (PortfolioManagementClaimNull)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden, new { ErrorCode = PortfoliosErrorCodes.PortfolioManagementClaimNull });
            }
            catch (PortfolioDetailsInsertUnauthorisedException)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden, new { ErrorCode = PortfoliosErrorCodes.PortfolioCompanyInsertUnauthorised });
            }
            catch (PortfolioDetailsExistsInPortfolio)
            {
                return Request.CreateResponse(HttpStatusCode.Accepted, new { ErrorCode = PortfoliosErrorCodes.PortfolioCompanyExistsInPortfolio });
            }
            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorCode = 1010 });
            }
        }

        [Route("{id}")]
        public HttpResponseMessage Delete(Guid portfolioId, Guid id)
        {
            try
            {
                if (!claimsChecker.ValidatePortfolioManagementClaim(this))
                    throw new PortfolioManagementClaimNull();

                PortfolioUserClaims userClaims = new PortfolioUserClaims();
                //if (Utils.UnitTestDetector.IsInUnitTest)
                //{
                //    userClaims.AddedByUserName = "ileana.popescu@sustainalytics.com";
                //    userClaims.AccountId = new Guid("528ea769-2d17-e411-92ce-6c3be5be9f98");
                //}
                //else
                //{
                    if (ClaimsPrincipal.Current != null)
                    {
                        userClaims.AddedByUserName = ClaimsPrincipal.Current.Identity.Name.ToLowerInvariant();
                    }
                //}
                _portfolioDetails.DeletePortfolioDetails(portfolioId, id, userClaims);

                //invalidate cache for parent resource (in this case we need it because CompaniesDto contains number of indicators)
                var cache = Configuration.CacheOutputConfiguration().GetCacheOutputProvider(Request);
                cache.RemoveStartsWith(Configuration.CacheOutputConfiguration().MakeBaseCachekey("Portfolios", "Get"));

                return Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (PortfolioManagementClaimNull)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden, new { ErrorCode = PortfoliosErrorCodes.PortfolioManagementClaimNull });
            }
            catch (PortfolioDetailsDeleteUnauthorisedException)
            {
                return Request.CreateResponse(HttpStatusCode.Forbidden, new { ErrorCode = 5004 });
            }

            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { ErrorCode = 1010 });
            }
        }
    }
}
